#include "ListParameter.h"

namespace czj {
namespace util {

ListParameter::ListParameter(const char *_describe, bool _nullable)
		: Parameter(_describe), nullable_(_nullable), hints_(), keys_(), expressions_(), defaults_(), values_() {
}

ListParameter::~ListParameter() {
}

Parameter::Type ListParameter::getType() const {
	return LIST;
}

bool ListParameter::isNullable() const {
	return nullable_;
}

const std::list<std::string> &ListParameter::getHints() const {
	return hints_;
}

bool ListParameter::bindKey(const char *_key, const char *_hint) {
	if (!keys_.insert(_key).second) {
		return false;
	}
	if (_hint != nullptr && _hint[0] != '\0') {
		hints_.push_back(std::string(_key).append(" <").append(_hint).append(">"));
	}
	else {
		hints_.push_back(std::string(_key));
	}
	return true;
}

bool ListParameter::matchKey(const char *_key, const char *_value) {
	if (keys_.find(_key) != keys_.cend()) {
		values_.push_back(_value);
		return true;
	}
	return false;
}

bool ListParameter::bindExpression(const char *_key, const char *_operator, const char *_hint, const char *_default) {
	expressions_.push_back(std::string(_key).append(_operator));
	if (_default != nullptr) {
		defaults_[_key] = _default;
		if (_hint != nullptr && _hint[0] != '\0') {
			hints_.push_back(std::string(_key).append("[").append(_operator).append(_hint).append("(").append(_default).append(")]"));
		}
		else {
			hints_.push_back(std::string(_key).append("[").append(_operator).append("(").append(_default).append(")]"));
		}
	}
	else {
		if (_hint != nullptr && _hint[0] != '\0') {
			hints_.push_back(std::string(_key).append(_operator).append("<").append(_hint).append(">"));
		}
		else {
			hints_.push_back(std::string(_key).append(_operator));
		}
	}
	return true;
}

bool ListParameter::matchExpression(const char *_expression) {
	const auto iterator = defaults_.find(_expression);
	if (iterator != defaults_.cend()) {
		values_.push_back(iterator->second);
		return true;
	}
	for (auto const &expression : expressions_) {
		if (expression.compare(0, expression.length(), _expression, expression.length()) == 0) {
			values_.push_back(_expression + expression.length());
			return true;
		}
	}
	return false;
}

const std::list<std::string> &ListParameter::getValues() const {
	return values_;
}

} // util
} // czj
